<?php
/**
 * @todo Unit test this...
 */
class Boss_Response {

    const HTTP_VERSION = "HTTP/1.1";
    
    protected $_headers = array();
    
    protected $_body;
    
    protected $_format;
    
    /**
     * Constructor
     */
    public function __construct($headers = null, $body = null, $format = null) {
    
        if (is_null($headers)) {
            $headers = array();
        }
        $this->setHeaders($headers)
             ->setBody($body)
             ->setFormat($format);
    
    }
    
    public function setFormat($format) {
    
        $this->_format = $format;
    
    }
    
    public function getFormat() {
    
        return $this->_format;
    
    }
    
    public function setHeaders($headers) {
    
        if (!is_array($headers)) {
            $headers = explode("\r\n", (string) $headers);
        }
        foreach ($headers as $header) {
            if (strpos($header, ':') === false) {
                $this->setStatus($header);
                continue;
            }
            list($name, $value) = explode(":", $header, 2);
            $this->setHeader($name, $value);
        }
        return $this;
    
    }
    
    public function setHeader($name, $value) {
    
        $this->_headers[trim(strtolower($name))] = array(trim($value));
    
    }
    
    public function addHeader($name, $value) {
    
        $this->_headers[trim(strtolower($name))][] = trim($value);
    
    }
    
    public function getHeaders() {
    
        $headers = array();
        foreach ($this->_headers as $name => $values) {
            foreach ($values as $value) {
                if (strpos($name, "-") !== false) {
                    $parts = explode('-', $name);
                } else {
                    $parts = array($name);
                }
                if ($name == 'etag') $parts = array('ETag');
                $parts = array_map('ucfirst', $parts);
                $name = implode('-', $parts);
                $headers[] = $name . ': ' . $value;
            }
        }
        return $headers;
    
    }
    
    public function getHeader($name) {
    
        $count = count($this->_headers[strtolower($name)]);
        if ($count > 1) return $this->_headers[strtolower($name)];
        else return $this->_headers[strtolower($name)][0];
    
    }
    
    public function getHeadersAsString() {
    
        $headers = $this->getHeaders();
        return implode("\r\n", $headers) . "\r\n";
    
    }

    public function setBody($body) {
    
        $this->_body = $body;
        return $this;
    
    }
    
    public function getBody() {
    
        return $this->_body;
    
    }
    
    public function setStatus($status) {
    
        if (strpos($status, self::HTTP_VERSION) !== false) {
            $status = str_replace(self::HTTP_VERSION, '', $status);
        }
        $this->_status = trim($status);
    
    }
    
    public function getStatus() {
    
        return $this->_status;
    
    }
    
    public function __toString() {
    
        $parts = array(
            self::HTTP_VERSION . " " . $this->getStatus(),
            $this->getHeadersAsString(),
            $this->getBody()
        );
        return implode("\r\n", $parts);
    
    }
    
    public function getDecoded() {
    
        switch($this->getFormat()) {
            case 'json':
                return json_decode($this->getBody());
                break;
            case 'xml':
                return new SimpleXmlElement($this->getBody());
                break;
        }
    
    }
    
    static public function generate($responseStr, $format = null) {
    
        list($headers, $body) = explode(chr(13) . chr(10) . chr(13) . chr(10), $responseStr);
        return new Boss_Response($headers, $body, $format);
    
    }

}